package keer.httpinterface.http;

import keer.httpinterface.HttpInterfaceException;
import keer.httpinterface.utils.HttpInterfaceFactories;

/**
 * http请求调用者,通过{@link #request(HttpRequest)}方法实现http远程接口请求。
 * 通过{@link #configure(HttpProperties)}方法配置http请求参数。<br/>
 * 接口提供静态方法{@link #getInstance()}和{@link #getInstance(ClassLoader)}获取默认的HttpRequester实例。
 * 可以通过在META-INF/httpinterface.factories文件中配置自定义的HttpRequester实现类。配置方式如下：<br/>
 * keer.httpinterface.http.HttpRequester=com.example.MyHttpRequester <br/>
 * 其中，com.example.MyHttpRequester为自定义的HttpRequester实现类。
 * @see HttpProperties
 * @see HttpRequest
 * @see HttpResponse
 * @see HttpInterfaceFactories
 *
 * @author Keer
 * @since 1.0.0
 */
public interface HttpRequester {
    /**
     * 配置{@link HttpRequester}实例
     * @param properties 配置参数
     * @throws HttpInterfaceException 配置失败时抛出的异常
     */
    void configure(HttpProperties properties) throws HttpInterfaceException;

    /**
     * 发送http请求
     * @param request 请求参数
     * @return 请求结果
     * @throws HttpInterfaceException 请求失败时抛出的异常
     */
    HttpResponse request(HttpRequest request) throws HttpInterfaceException;

    /**
     * 获取HttpRequester实例, 默认使用{@link URLHttpRequester},
     * 当META-INF/httpinterface.factories配置了自定义的HttpRequester实现类时，使用配置的实现类。
     * 如果META-INF/httpinterface.factories配置了多个实现类，则使用最后一个配置的实现类。
     * @param classLoader 加载{@link HttpRequester}实现类时使用的加载器
     * @return HttpRequester实例
     * @throws HttpInterfaceException 获取实例失败时抛出的异常
     */
    static HttpRequester getInstance(ClassLoader classLoader) throws HttpInterfaceException {
        HttpRequester requester = null;
        try {
            requester = HttpInterfaceFactories.loadLastOneFactoryInstance(classLoader, HttpRequester.class);
        } catch (Exception e) {
            throw new HttpInterfaceException("Create requester fail.", e);
        }
        if (requester == null) {
            requester = new URLHttpRequester();
        }
        return requester;
    }

    /**
     * 获取HttpRequester实例, 默认使用{@link URLHttpRequester},
     * 当META-INF/httpinterface.factories配置了自定义的HttpRequester实现类时，使用配置的实现类。
     * 如果META-INF/httpinterface.factories配置了多个实现类，则使用最后一个配置的实现类。
     * @return HttpRequester实例
     * @throws HttpInterfaceException 获取实例失败时抛出的异常
     */
    static HttpRequester getInstance() throws HttpInterfaceException {
        return getInstance(Thread.currentThread().getContextClassLoader());
    }
}
